/*
    c++ curl libcurl wrapper demo project
    http://code.google.com/p/curlwork/
*/

#include "curlwork/info.hpp"
#include "curlwork/operation.hpp"
#include "curlwork/queue_reactor.hpp"

#include <string>
#include <iostream>
#include <cctype>

// demo 1. count 'windows' word on page

class word_counter
{
    typedef curlwork::operation<word_counter> operation_type;

    operation_type webop_;

    std::string word_;
    std::size_t count_;

    std::size_t index_;

public:

    word_counter(const std::string& word = "windows")
        : webop_(*this)
        , word_(word)
        , count_(0)
        , index_(0)
    {   }

    template<typename T>
    void start(T& reactor, const char *page)
    {
        /*
            Remember libcurl takes !!!POINTER!!! to url
            watch out for the lifetime of the object
        */

        webop_.set(curlwork::url(page));

        webop_.set(operation_type::complete(&word_counter::complete));
        webop_.set(operation_type::fail(&word_counter::fail));
        webop_.set(operation_type::write(&word_counter::write));

        // some usefull options
        //
        //webop_.set(curlwork::option(CURLOPT_VERBOSE, 1L));

        //webop_.set(curlwork::username("user"));
        //webop_.set(curlwork::password("user"));

        // for https
        // http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
        //webop_.set(curlwork::option(CURLOPT_SSLVERSION, 3L));
        //webop_.set(curlwork::option(CURLOPT_SSL_VERIFYHOST, 0L));
        //webop_.set(curlwork::option(CURLOPT_SSL_VERIFYPEER, 0L));

        reactor.add(webop_);
    }

    // write handler
    std::size_t write(const char *buffer,
                      std::size_t size, std::size_t nmemb) throw()
    {
        for (std::size_t i = 0; i < nmemb; ++i)
        {
            if (index_ == word_.size())
            {
                ++count_;
                index_ = 0;
            }

            char c = static_cast<char>(std::tolower(buffer[i]));
            if (c != word_[index_++])
                index_ = 0;
        }

        return nmemb;
    }

    // complete handler
    void complete() throw()
    {
        std::cout << curlwork::effective_url(webop_) << std::endl
                  << " windows word count : " << count_ << std::endl
                  << std::endl;
    }

    // fail handler
    void fail(curlwork::error_type error) throw()
    {
        std::cerr << curlwork::effective_url(webop_) << std::endl
                  << " fail : " << curlwork::response_code(webop_)
                  << " - " << curlwork::description(error) << std::endl
                  << std::endl;
    }
};

int main()
{
    curlwork::queue_reactor reactor;

    word_counter word1;
    word1.start(reactor, "http://windows.microsoft.com/en-US/windows/home");

    // invalid url
    // start second operaion with invalid url
    word_counter word2;
    word2.start(reactor, "http://windows.microsoft.com/en-US/winws/hme");

    try
    {
        while (reactor.react())
        {   }
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}
